package org.ricks.net.action.rpc;

import java.util.Arrays;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;

public final class RpcMetrics {
    private final LongAdder totalRequests = new LongAdder();
    private final LongAdder successRequests = new LongAdder();
    private final LongAdder timeoutRequests = new LongAdder();
    private final LongAdder droppedResponses = new LongAdder();
    private final LongAdder decodeErrors = new LongAdder();
    private final LongAdder processErrors = new LongAdder();
    private final LongAdder invokeErrors = new LongAdder();
    private final LongAdder typeErrors = new LongAdder();
    private final LongAdder rejectedRequest = new LongAdder();
    private final LongAdder[] latencyBuckets = new LongAdder[8];

    private final LongAccumulator minLatency = new LongAccumulator(Long::min, Long.MAX_VALUE);
    private final LongAccumulator maxLatency = new LongAccumulator(Long::max, Long.MIN_VALUE);
    private final LongAdder totalLatency = new LongAdder();

    // 优化12: 添加服务端指标
    private final LongAdder processedRequests = new LongAdder();
    private final LongAdder processSuccess = new LongAdder();
    private final LongAccumulator minProcessTime = new LongAccumulator(Long::min, Long.MAX_VALUE);
    private final LongAccumulator maxProcessTime = new LongAccumulator(Long::max, Long.MIN_VALUE);
    private final LongAdder totalProcessTime = new LongAdder();

    // 添加 pending requests 统计
    private long pendingRequests = 0;

    public RpcMetrics() {
        Arrays.setAll(latencyBuckets, i -> new LongAdder());
    }

    public void setPendingRequests(long pending) {
        this.pendingRequests = pending;
    }

    // 记录处理成功
    public void recordProcessSuccess(long durationNanos) {
        processedRequests.increment();
        processSuccess.increment();
        minProcessTime.accumulate(durationNanos);
        maxProcessTime.accumulate(durationNanos);
        totalProcessTime.add(durationNanos);
    }

    // 记录处理错误
    public void recordProcessError() {
        processedRequests.increment();
        processErrors.increment();
    }

    public void recordTotalRequests () {
        totalRequests.increment();
    }


    // 记录响应
    public void recordResponse(long latencyNanos, boolean success) {
        if (success) {
            successRequests.increment();
            minLatency.accumulate(latencyNanos);
            maxLatency.accumulate(latencyNanos);
            totalLatency.add(latencyNanos);
            recordLatency(latencyNanos);
        } else {
            timeoutRequests.increment();
        }
    }

    public void recordTimeout() {
        timeoutRequests.increment();
    }

    // 记录丢弃的响应
    public void recordDroppedResponse() {
        droppedResponses.increment();
    }

    // 记录解码错误
    public void recordDecodeError() {
        decodeErrors.increment();
    }


    // 记录调用错误
    public void recordInvokeError() {
        invokeErrors.increment();
    }

    //记录类型转换错误
    public void recordTypeError() {
        typeErrors.increment();
    }

    //记录拒绝请求
    public void recordRejectedRequest() {
        rejectedRequest.increment();
    }

    // 全局统计
    public void recordLatency(long latencyNanos) {
        double ms = latencyNanos / 1_000_000.0;
        int bucket = ms < 1 ? 0 : ms < 5 ? 1 : ms < 10 ? 2 : ms < 50 ? 3 : ms < 100 ? 4 : ms < 500 ? 5 : ms < 1000 ? 6 : 7;
        latencyBuckets[bucket].increment();
    }

    // 打印统计信息
    public void printStats() {
        long total = totalRequests.sum();
        long success = successRequests.sum();
        long timeout = timeoutRequests.sum();
        long processed = processedRequests.sum();
        long processSuccessCount = processSuccess.sum();

        double successRate = total > 0 ? success * 100.0 / total : 0;
        double timeoutRate = total > 0 ? timeout * 100.0 / total : 0;
        double avgLatency = success > 0 ? totalLatency.sum() / (double) success : 0;
        double processSuccessRate = processed > 0 ? processSuccessCount * 100.0 / processed : 0;
        double avgProcessTime = processSuccessCount > 0 ? totalProcessTime.sum() / (double) processSuccessCount : 0;

        // 计算延迟分布百分比
        String[] ranges = {"<1ms", "1-5ms", "5-10ms", "10-50ms", "50-100ms", "100-500ms", "0.5-1s", ">1s"};
        long[] bucketCounts = new long[ranges.length];
        for (int i = 0; i < ranges.length; i++) {
            bucketCounts[i] = getLatencyBucket(i);
        }

        System.out.println("================================ RPC Metrics ================================");

        // 请求统计
        System.out.printf("%-30s: %,d\n", "Total Requests", total);
        System.out.printf("%-30s: %,d (%.2f%%)\n", "Successful Requests", success, successRate);
        System.out.printf("%-30s: %,d (%.2f%%)\n", "Timeout Requests", timeout, timeoutRate);
        System.out.printf("%-30s: %,d\n", "Processed Requests", processed);
        System.out.printf("%-30s: %,d (%.2f%%)\n", "Processing Success", processSuccessCount, processSuccessRate);
        System.out.println();

        // 延迟统计
        System.out.printf("%-30s: %8.3f ms\n", "Min Latency", minLatency.get() / 1_000_000.0);
        System.out.printf("%-30s: %8.3f ms\n", "Max Latency", maxLatency.get() / 1_000_000.0);
        System.out.printf("%-30s: %8.3f ms\n", "Avg Latency", avgLatency / 1_000_000.0);
        System.out.printf("%-30s: %8.3f ms\n", "Min Processing Time", minProcessTime.get() / 1_000_000.0);
        System.out.printf("%-30s: %8.3f ms\n", "Max Processing Time", maxProcessTime.get() / 1_000_000.0);
        System.out.printf("%-30s: %8.3f ms\n", "Avg Processing Time", avgProcessTime / 1_000_000.0);
        System.out.println();

        // 错误统计
        System.out.printf("%-30s: %,d\n", "Dropped Responses", droppedResponses.sum());
        System.out.printf("%-30s: %,d\n", "Decode Errors", decodeErrors.sum());
        System.out.printf("%-30s: %,d\n", "Process Errors", processErrors.sum());
        System.out.printf("%-30s: %,d\n", "Invoke Errors", invokeErrors.sum());
        System.out.printf("%-30s: %,d\n", "Type Errors", typeErrors.sum());
        System.out.printf("%-30s: %,d\n", "Rejected Requests", rejectedRequest.sum());
        System.out.println();

        // 延迟分布
        System.out.println("Latency Distribution (Successful Requests):");
        System.out.println("--------------------------------------------");
        System.out.printf("%-12s  %12s  %10s\n", "Bucket", "Count", "Percentage");
        System.out.println("--------------------------------------------");

        for (int i = 0; i < ranges.length; i++) {
            double percentage = success > 0 ? bucketCounts[i] * 100.0 / success : 0;
            System.out.printf("%-12s  %,12d  %9.2f%%\n",
                    ranges[i], bucketCounts[i], percentage);
        }

        System.out.println("========================================================================");
    }

    private long getLatencyBucket(int index) {
        LongAdder longAdder = latencyBuckets[index];
        return longAdder.sum();
    }
}

class CommandMetrics {
    private final LongAdder success = new LongAdder();
    private final LongAdder failures = new LongAdder();
    private final LongAccumulator minLatency = new LongAccumulator(Long::min, Long.MAX_VALUE);
    private final LongAccumulator maxLatency = new LongAccumulator(Long::max, Long.MIN_VALUE);
    private final LongAdder totalLatency = new LongAdder();

    public void recordLatency(long nanos) {
        minLatency.accumulate(nanos);
        maxLatency.accumulate(nanos);
        totalLatency.add(nanos);
    }

    public double successRate() {
        long total = success.sum() + failures.sum();
        return total > 0 ? success.sum() * 100.0 / total : 0;
    }
}